﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class People {
public:
	virtual void Mypro() {
		cout << "People Mypro" << endl; 
	}
};

class wanzhaojun : public People {
public:
	// 重写父类虚函数 
	void Mypro() {
		cout << "wangzhaojun Mypro" << endl;
	}
};

class diaochan : public People {
public:
	// 重写父类虚函数 
	void Mypro() {
		cout << "diaochan Mypro" << endl;
	}
};

class xishi : public People {
public:
	// 重写父类虚函数 
	void Mypro() {
		cout << "xishi Mypro" << endl;
	}
};

// 同一个操作  
void doLogin(People *p) {
	p->Mypro(); 
}

/*
多态发生的三个条件：
1. 子类继承父类；
1. 子类重写父类的虚函数；
2. 父类指针指向子类对象。

多态的实现原理：
1. 编译器只要发现类中有虚函数，编译器就会创建一张表，表里放类中所有虚函数的入口地址；
2. 编译器会在类对象中安插一个虚函数表指针，虚函数表指针指向本类的虚函数表；
3. 虚函数表指针是从父类继承下来的，虚函数表指针指向父类的虚函数表。编译器为了初始化从父类继承过来的
   虚函数表指针，编译器在我们的所有构造函数中添加了初始化虚函数指针的代码，让从父类继承过来的虚函数
   表指针指向子类自己的虚函数表；
4. 当编译器发现子类重写了父类的虚函数，那么子类重写的函数就会覆盖掉虚函数表对应的父类虚函数（注意，
   子类中重写父类的虚函数，该函数在子类中不是virtual的了，但是该函数的入口地址仍会放在虚函数表中）；
5. 当我们通过父类指针去调用speak函数时，编译器会根据Animal指针指向的内存空间中的虚函数表来找到实际
   需要调用的speak函数。
*/
void test01() {
	People *p = NULL;
	p = new wanzhaojun;
	doLogin(p);
	delete p;
	p = new xishi;
	doLogin(p);
	delete p;
	p = new diaochan;
	doLogin(p);
	delete p; 
}

int main()
{

	test01(); 

	system("pause");
	return EXIT_SUCCESS;
}